﻿// VERSION = '1.0.1'
if (!jQuery) { throw new Error("xfront.js requires jQuery") }

//------app-----------------------------------------------------------------------------------------

// querier options: {done(data, page)}
+function ($) {
    "use strict";

    // Class
    var Querier = function (element, options) {
        this.$element = $(element);
        this.options = $.extend({}, Querier.DEFAULTS, options);
    };

    Querier.VERSION = '1.0.1';

    Querier.DEFAULTS = {
        "done": undefined
    };

    Querier.prototype.query = function (pageIndex) {
        var instance = this;
        var $querier = this.$element;
        var $done = this.options.done;
        var obj = $querier.serializeObject();
        obj.pageIndex = pageIndex;
        $.getJSON('/Data', obj, function (data, textStatus, jqXHR) {
            $querier.find('[data-plugin=renderer]').renderer(data);

            // filterer
            $querier.find('[data-plugin=filterer]').each(function (index, element) {
                var $filterer = $(element);
                if ($filterer.is(':button')) {
                    $filterer.click(function (event) {
                        instance.query(0);
                        event.preventDefault();
                    });
                }
            });

            // sorter
            $querier.find('[data-plugin=sorter]').each(function (index, element) {
                var $sorter = $(element);
                if ($sorter.is('select')) {
                    sorter.change(function (event) {
                        instance.query(0);
                        event.preventDefault();
                    });
                }
            });

            // tableHeadSorter
            $querier.find('[data-plugin=tableHeadSorter]').tableHeadSorter({
                "change": function () {
                    instance.query(0);
                }
            });

        }).done(function (data, textStatus, jqXHR) {
            var r_data = data;
            var r_page;
            $.getJSON('/Data/Count', obj, function (data, textStatus, jqXHR) {
                var pageIndexChange = function (pageIndex) {
                    instance.query(pageIndex);
                };

                var itemCount = data.Count;
                var pageIndex = obj.pageIndex;

                var pageSize;
                var pageSizer = $querier.find('[data-plugin=pageSizer]');
                if (pageSizer.is('select')) {
                    pageSize = pageSizer.val();
                    pageSizer.change(function (event) {
                        instance.query(0);
                        event.preventDefault();
                    });
                }

                var pageCount = Math.ceil(itemCount / pageSize);

                r_page = {};
                r_page.itemCount = itemCount;
                r_page.pageIndex = pageIndex;
                r_page.pageSize = pageSize;
                r_page.pageCount = pageCount;

                $querier.find('[data-plugin=pagination]').pagination({
                    "pageIndex": pageIndex,
                    "pageCount": pageCount,
                    "change": function (index) {
                        pageIndexChange(index);
                    }
                });
                $querier.find('[data-plugin=paginationGo]').paginationGo({
                    "pageIndex": pageIndex,
                    "pageCount": pageCount,
                    "change": function (index) {
                        pageIndexChange(index);
                    }
                });
                $querier.find('[data-plugin=paginationInfo]').paginationInfo({
                    "pageSize": pageSize,
                    "pageIndex": pageIndex,
                    "itemCount": itemCount
                });
            });
        }).done(function (data, textStatus, jqXHR) {
            if ($done != null) {
                $done(r_data, r_page);
            }
        });
    };

    // Plugin 
    function Plugin(options) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.querier');
            var opts = typeof options == 'object' && options;
            if (!data) $this.data('xd.querier', (data = new Querier(this, opts)));
            if (options == 'query') data.query(0);            
        })
    }

    var old = $.fn.querier;

    $.fn.querier = Plugin;
    $.fn.querier.Constructor = Querier;

    // No conflict
    $.fn.querier.noConflict = function () {
        $.fn.querier = old;
        return this;
    };

}(jQuery);

// Creator

// Editor

// ?Delete

//------site----------------------------------------------------------------------------------------

// queryPage options: {done(data, page)}
+function ($) {
    "use strict";

    // Class
    var QueryPage = function (element, options) {
        this.$element = $(element);
        this.options = $.extend({}, QueryPage.DEFAULTS, options);
    };

    QueryPage.VERSION = '1.0.1';

    QueryPage.DEFAULTS = {
        "done": undefined
    };

    QueryPage.prototype.initialize = function () {
        var $querier = this.$element;
        var $done = this.options.done;

        var searchObj = $.parseObject();
        if (searchObj.pageIndex == null) searchObj.pageIndex = 0;
        $querier.deserializeObject(searchObj);

        var obj = $querier.serializeObject();
        obj.pageIndex = searchObj.pageIndex;

        $.getJSON('/Data', obj, function (data, textStatus, jqXHR) {
            $querier.find('[data-plugin=renderer]').renderer(data);
        }).done(function (data, textStatus, jqXHR) {

            // filterer
            $querier.find('[data-plugin=filterer]').each(function (index, element) {
                var filterer = $(element);
                if (filterer.is(':button')) {
                    var data_name = filterer.attr('data-name');
                    filterer.click(function (event) {
                        var elementNames = filterer.attr('data-value-elements').split(',');
                        for (var i = 0; i < elementNames.length; i++) {
                            var elementName = $.trim(elementNames[i]);
                            var element = $('[name=' + elementName + ']');
                            if (element.length > 0) {
                                searchObj[elementName] = element.val();
                            }
                        }
                        if (data_name == null) {
                            delete searchObj.name
                        }
                        else {
                            searchObj.name = data_name;
                        }
                        delete searchObj.pageIndex;
                        window.location.href = $.toEncodedUrl(searchObj);
                        event.preventDefault();
                    });
                }
            });

            // sorter
            $querier.find('[data-plugin=sorter]').each(function (index, element) {
                var sorter = $(element);
                if (sorter.is('select')) {
                    var name = sorter.attr('name');
                    sorter.change(function (event) {
                        var sort = sorter.val();
                        searchObj[name] = sort;
                        delete searchObj.pageIndex;
                        window.location.href = $.toEncodedUrl(searchObj);
                        event.preventDefault();
                    });
                }
            });

            // tableHeadSorter
            $querier.find('[data-plugin=tableHeadSorter]').tableHeadSorter({
                "change": function (value) {
                    searchObj = $.extend(searchObj, value);
                    delete searchObj.pageIndex;
                    window.location.href = $.toEncodedUrl(searchObj);
                }
            });

            var r_data = data;
            var r_page;
            $.getJSON('/Data/Count', obj, function (data, textStatus, jqXHR) {
                var pageIndexChange = function (pageIndex) {
                    if (pageIndex == 0) {
                        delete searchObj.pageIndex;
                    }
                    else {
                        searchObj.pageIndex = pageIndex;
                    }
                    window.location.href = $.toEncodedUrl(searchObj);
                };

                var pageSizeChange = function (name, pageSize) {
                    searchObj[name] = pageSize;
                    delete searchObj.pageIndex;
                    window.location.href = $.toEncodedUrl(searchObj);
                };

                var itemCount = data.Count;

                var pageIndex = searchObj.pageIndex;

                var pageSize;
                var pageSizer = $querier.find('[data-plugin=pageSizer]');
                if (pageSizer.is('select')) {
                    var name = pageSizer.attr('name');
                    pageSize = pageSizer.val();
                    pageSizer.change(function (event) {
                        var size = pageSizer.val();
                        pageSizeChange(name, size);
                        event.preventDefault();
                    });
                }

                var pageCount = Math.ceil(itemCount / pageSize);

                r_page = {};
                r_page.itemCount = itemCount;
                r_page.pageIndex = pageIndex;
                r_page.pageSize = pageSize;
                r_page.pageCount = pageCount;

                $querier.find('[data-plugin=pagination]').pagination({
                    "pageIndex": pageIndex,
                    "pageCount": pageCount,
                    "change": function (index) {
                        pageIndexChange(index);
                    }
                });
                $querier.find('[data-plugin=paginationGo]').paginationGo({
                    "pageIndex": pageIndex,
                    "pageCount": pageCount,
                    "change": function (index) {
                        pageIndexChange(index);
                    }
                });
                $querier.find('[data-plugin=paginationInfo]').paginationInfo({
                    "pageSize": pageSize,
                    "pageIndex": pageIndex,
                    "itemCount": itemCount
                });

            }).done(function (data, textStatus, jqXHR) {
                if ($done != null) {
                    $done(r_data, r_page);
                }
            });
        });
    };

    // Plugin 
    function Plugin(options) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.queryPage');
            var opts = typeof options == 'object' && options;
            if (!data) $this.data('xd.queryPage', (data = new QueryPage(this, opts)));
            data.initialize();
        })
    }

    var old = $.fn.queryPage;

    $.fn.queryPage = Plugin;
    $.fn.queryPage.Constructor = QueryPage;

    // No conflict
    $.fn.queryPage.noConflict = function () {
        $.fn.queryPage = old;
        return this;
    };

}(jQuery);

// createForm options: {submitText} // requires bootstrapValidator
+function ($) {
    "use strict";

    // Class
    var CreateForm = function (form, options) {
        this.$form = $(form);
        this.options = $.extend({}, CreateForm.DEFAULTS, options);
    };

    CreateForm.VERSION = '1.0.1';

    CreateForm.DEFAULTS = {
        submitText: 'Create'
    };

    CreateForm.prototype.initialize = function () {
        var $form = this.$form;
        var submitText = this.options.submitText;
        var $submit = $form.find(':submit');
        var redirect = $submit.attr("data-redirect-url") + window.location.search;
        $submit.val(submitText).attr("disabled", true);

        var data_name = $form.attr('data-name');
        var getUrl = (data_name == null) ? '/Data' : '/Data?name=' + data_name;
        $.getJSON(getUrl, {}, function (data, textStatus, jqXHR) {
            var obj = $.isArray(data) ? data[0] : data;
            $form.deserializeObject(obj);
        }).done(function () {
            $form.bootstrapValidator({
                submitHandler: function (validator, form, submitButton) {
                    var obj = $(form).serializeObject();
                    $.ajax({
                        "async": true,
                        "url": "/Data",
                        "type": "POST",
                        "contentType": "application/json",
                        "data": JSON.stringify(obj),
                        "dataType": "json",
                        "success": function (data, textStatus, jqXHR) {
                            $form.find(':password').val('');
                            if (data.Error == null) {
                                window.location.href = redirect;
                            }
                            else {
                                $form.find('[data-plugin=backendErrorRenderer]').backendErrorRenderer(data.Error);
                            }
                        },
                    });
                },
            });

            $form.find(':submit').attr("disabled", false);
        });
    };

    // Plugin 
    function Plugin(options) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.createForm');
            var opts = typeof options == 'object' && options;
            if (!data) {
                $this.data('xd.createForm', (data = new CreateForm(this, opts)));
                data.initialize();
            }
        })
    }

    var old = $.fn.createForm;

    $.fn.createForm = Plugin;
    $.fn.createForm.Constructor = CreateForm;

    // No conflict
    $.fn.createForm.noConflict = function () {
        $.fn.createForm = old;
        return this;
    };

}(jQuery);

// editForm options: {submitText} // requires bootstrapValidator
+function ($) {
    "use strict";

    // Class
    var EditForm = function (form, options) {
        this.$form = $(form);
        this.options = $.extend({}, EditForm.DEFAULTS, options);
    };

    EditForm.VERSION = '1.0.1';

    EditForm.DEFAULTS = {
        submitText: 'Edit'
    };

    EditForm.prototype.initialize = function () {
        var $form = this.$form;
        var submitText = this.options.submitText;
        var $submit = $form.find(':submit');
        var redirect = $submit.attr("data-redirect-url") + window.location.search;
        $submit.val(submitText).attr("disabled", true);

        var data_name = $form.attr('data-name');
        var getUrl = (data_name == null) ? '/Data' : '/Data?name=' + data_name;
        $.getJSON(getUrl, {}, function (data, textStatus, jqXHR) {
            var obj = $.isArray(data) ? data[0] : data;
            $form.deserializeObject(obj);
        }).done(function (data, textStatus, jqXHR) {
            $form.bootstrapValidator({
                submitHandler: function (validator, form, submitButton) {
                    var obj = $form.serializeObject();
                    $.ajax({
                        "async": true,
                        "url": "/Data",
                        "type": "PUT",
                        "contentType": "application/json",
                        "data": JSON.stringify(obj),
                        "dataType": "json",
                        "success": function (data, textStatus, jqXHR) {
                            $form.find(':password').val('');
                            if (data.Error == null) {
                                window.location.href = redirect;
                            }
                            else {
                                $form.find('[data-plugin=backendErrorRenderer]').backendErrorRenderer(data.Error);
                            }
                        },
                    });
                },
            });

            $form.find(':submit').attr("disabled", false);
        });
    };

    // Plugin 
    function Plugin(options) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.editForm');
            var opts = typeof options == 'object' && options;
            if (!data) {
                $this.data('xd.editForm', (data = new EditForm(this, opts)));
                data.initialize();
            }
        })
    }

    var old = $.fn.editForm;

    $.fn.editForm = Plugin;
    $.fn.editForm.Constructor = EditForm;

    // No conflict
    $.fn.editForm.noConflict = function () {
        $.fn.editForm = old;
        return this;
    };

}(jQuery);

// deleteForm
+function ($) {
    "use strict";

    // Class
    var DeleteForm = function (element) {
        this.$element = $(element);
    };

    DeleteForm.VERSION = '1.0.1';

    DeleteForm.prototype.initialize = function () {
        var $el = this.$element;
        var $submit = $el.find(':submit');
        var redirect = $submit.attr("data-redirect-url") + window.location.search;

        $submit.click(function (event) {
            event.preventDefault();

            $.ajax({
                "async": true,
                "url": "/Data",
                "type": "DELETE",
                "contentType": "application/json",
                "data": {},
                "dataType": "json",
                "success": function (data, textStatus, jqXHR) {
                    $el.find(':password').val('');
                    if (data.Error == null) {
                        window.location.href = redirect;
                    }
                    else {
                        $el.find('[data-plugin=backendErrorRenderer]').backendErrorRenderer(data.Error);
                    }
                },
            });

        });
    };

    // Plugin 
    function Plugin(options) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.deleteForm');
            var opts = typeof options == 'object' && options;
            if (!data) {
                $this.data('xd.deleteForm', (data = new DeleteForm(this, opts)));
                data.initialize();
            }
        })
    }

    var old = $.fn.deleteForm;

    $.fn.deleteForm = Plugin;
    $.fn.deleteForm.Constructor = DeleteForm;

    // No conflict
    $.fn.deleteForm.noConflict = function () {
        $.fn.deleteForm = old;
        return this;
    };

}(jQuery);

// $('select[data-name]').initializer()
+function ($) {
    "use strict";

    // Class
    var Initializer = function (element) {
        this.$element = $(element);
    };

    Initializer.VERSION = '1.0.1';

    Initializer.prototype.initialize = function () {
        var $el = this.$element;
        var emptyHtml = $el.attr('data-empty-html');
        var name = $el.attr('data-name');
        $.getJSON('/Data?name=' + name, {}, function (data) {
            $el.renderer(data);
            if (emptyHtml != null) {
                var html = '<option selected="selected" value="">' + emptyHtml + '</option>';
                html += $el.html();
                $el.html(html);
            }
        });
    };

    // Plugin 
    function Plugin(options) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.initializer');
            var opts = typeof options == 'object' && options;
            if (!data) {
                $this.data('xd.initializer', (data = new Initializer(this, opts)));

                $.ajaxSettings.async = false;
                data.initialize();
                $.ajaxSettings.async = false;
            }
        })
    }

    var old = $.fn.initializer;

    $.fn.initializer = Plugin;
    $.fn.initializer.Constructor = Initializer;

    // No conflict
    $.fn.initializer.noConflict = function () {
        $.fn.initializer = old;
        return this;
    };

}(jQuery);

//------plugins-------------------------------------------------------------------------------------

// serializeObject()
+function ($) {
    "use strict";

    var getElementValue = function (element) {
        var value = undefined;

        if ($(element).is('select')) {
            value = $(element).val();
        }

        if ($(element).is('textarea')) {
            value = $(element).val();
            value = value.replace(/\n/gm, '\\r\\n');
        }

        if ($(element).is('input')) {
            var type = $(element).attr('type');
            switch (type) {
                case 'checkbox':
                    value = $(element).prop("checked");
                    break;
                case 'file':
                case 'image':
                case 'button':
                case 'submit':
                case 'reset':
                    break;
                default:
                    value = $(element).val();
            }
        }

        var dataType = $(element).attr('data-data-type');
        if (dataType == 'Date') {
            var format = $(element).attr('data-date-format');
            var date = $.parseDate(value, format);
            value = $.toDateString(date, 'json');
        }

        if (dataType == 'Number') {
            value = +value;
        }

        if (dataType == 'Boolean') {
            if (value.toString() == 'true') value = true;
            if (value.toString() == 'false') value = false;
        }

        return value;
    };

    var SerializeObject = function (element) {
        var obj = {};
        $(element).find(':input[name]').each(function (index, el) {
            var name = $(el).attr('name');
            var value = getElementValue(el);
            if (value != null) obj[name] = value;
        });
        return obj;
    };

    SerializeObject.VERSION = '1.0.1';

    // Plugin
    var old = $.fn.serializeObject;

    $.fn.serializeObject = function () {
        var result = {};
        this.each(function () {
            var obj = SerializeObject(this);
            result = $.extend({}, result, obj);
        })
        return result;
    };

    // No conflict
    $.fn.serializeObject.noConflict = function () {
        $.fn.serializeObject = old;
        return this;
    };

}(jQuery);

// deserializeObject(obj)
+function ($) {
    "use strict";
    var setElementValue = function (element, value) {
        var val = value;

        if ($.isDateJson(val)) {
            var date = $.parseDate(val);
            var format = $(element).attr('data-date-format');
            val = $.toDateString(date, format);
        }
        else {
            var format = $(element).attr('data-date-format');
            if (format != null) {
                var date = $.parseDate(val);
                val = $.toDateString(date, format);
            }
        }

        if ($(element).is('select,textarea')) {
            $(element).val(val);
        }

        if ($(element).is('input')) {
            var type = $(element).attr('type');
            switch (type) {
                case 'checkbox':
                case 'radio':
                    var el_val = $(element).val();
                    if (el_val == 'on') {
                        if (val.toString() == 'true') {
                            $(element).prop("checked", true);
                        }
                        else {
                            $(element).prop("checked", false);
                        }
                    }
                    else {
                        $(element).prop("checked", el_val == val);
                    }
                    break;
                default:
                    $(element).val(val);
                    break;
            }
        }
    }

    var DeserializeObject = function (element, obj) {
        if ($.isArray(obj)) {
            for (var i = 0; i < obj.length; i++) {
                var single = obj[i];
                for (var name in single) {
                    var val = single[name];
                    $(element).find(':checkbox[name=' + name + ']').filter('[value=' + val + ']').prop("checked", true);
                }
            }
            return;
        }

        $(element).find(':input[name]').each(function (index, el) {
            var name = $(el).attr('name');
            var value = obj[name];
            if (value != undefined) setElementValue(el, value);
        });
    };

    DeserializeObject.VERSION = '1.0.1';

    // Plugin
    var old = $.fn.deserializeObject;

    $.fn.deserializeObject = function (obj) {
        return this.each(function () {
            DeserializeObject(this, obj);
        })
    };

    // No conflict
    $.fn.deserializeObject.noConflict = function () {
        $.fn.deserializeObject = old;
        return this;
    };

}(jQuery);

// renderer(data)
+function ($) {
    "use strict";

    var render = function ($container, data) {

        var getHtml = function (template, data) {
            //{{...}}
            var var_statements = '';
            for (var name in data) {
                var value = data[name];
                if (value == null) value = '';

                if ($.isDateJson(value)) {
                    var date = $.parseDate(value);
                    value = $.toDateString(date);
                }

                var_statements += ' var ' + name + '="' + value + '";';
            }
            var result = template.replace(/\{{2}.*?\}{2}/g, function (word) {
                var exp = word.slice(2, -2);
                exp = var_statements + ' ' + exp;
                return eval(exp);
            });
            return result;
        }

        var $cont = $container;
        var html = $cont.attr('data-html');
        if (html == null) {
            html = $cont.html();
            $cont.attr('data-html', html);
            $cont.html('');
        }

        if (data == null) return;

        var aggr = '';
        $.each(data, function (index, item) {
            aggr += getHtml(html, item);
        });
        $cont.html(aggr);
        $cont.removeClass('hidden').removeClass('invisible');

        $cont.find('[data-date-format]').each(function (index, element) {
            var dateFormat = $(element).attr('data-date-format');
            if ($(element).is(':input')) {
                var value = $(element).val();
                if (value != '') {
                    var date = $.parseDate(value);
                    value = $.toDateString(date, dateFormat);
                    $(element).val(value);
                }
            }
            else {
                var text = $(element).text();
                if (text != '') {
                    var date = $.parseDate(text);
                    text = $.toDateString(date, dateFormat);
                    $(element).text(text);
                }
            }
        });
    };

    // Renderer
    var Renderer = function (container) {
        this.$container = $(container);
    };

    Renderer.VERSION = '1.0.1';

    Renderer.prototype.render = function (data) {
        render(this.$container, data);
    };

    // Plugin 
    var old = $.fn.renderer;

    $.fn.renderer = function (data) {
        return this.each(function () {
            var $this = $(this);
            var a_data = $this.data('xd.renderer');
            if (!a_data) $this.data('xd.renderer', (a_data = new Renderer(this)));
            a_data.render(data);
        })
    };

    $.fn.renderer.Constructor = Renderer;

    // No conflict
    $.fn.renderer.noConflict = function () {
        $.fn.renderer = old;
        return this;
    };

}(jQuery);

// backendErrorRenderer(error)
+function ($) {
    "use strict";

    // Class
    var BackendErrorRenderer = function (element) {
        this.$element = $(element);
    };

    BackendErrorRenderer.VERSION = '1.0.1';

    BackendErrorRenderer.prototype.render = function (error) {
        var html = '';
        if (error.ExceptionType == 'XData.Data.Element.Validation.ElementValidationException') {
            var errorMessage = error.ValidationErrors.ValidationError.ErrorMessage;
            if (errorMessage == null) {
                for (var index in error.ValidationErrors.ValidationError) {
                    var err = error.ValidationErrors.ValidationError[index];
                    html += '<li>' + err.ErrorMessage + '</li>';
                }
            }
            else {
                html = '<li>' + errorMessage + '</li>';
            }
        }
        else {
            html = '<li>' + error.ExceptionMessage + '</li>';
        }

        var $el = this.$element;
        if (!$el.is('ul,ol')) {
            html = '<ul>' + html + '</ul>';
        }

        $el.html(html);
    };

    // Plugin 
    var old = $.fn.backendErrorRenderer;

    $.fn.backendErrorRenderer = function (error) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.backendErrorRenderer');
            if (!data) $this.data('xd.backendErrorRenderer', (data = new BackendErrorRenderer(this)));
            data.render(error);
        })
    };

    $.fn.backendErrorRenderer.Constructor = BackendErrorRenderer;

    // No conflict
    $.fn.backendErrorRenderer.noConflict = function () {
        $.fn.backendErrorRenderer = old;
        return this;
    };

}(jQuery);

// pagination options: {prev,next,pageIndex,pageCount,change(pageIndex)}
+function ($) {
    "use strict";

    // Class
    var Pagination = function (element, options) {
        this.$element = $(element);

        var data = {};
        var prev = this.$element.attr('data-prev');
        if (prev != null) data.prev = prev;
        var next = this.$element.attr('data-next');
        if (next != null) data.next = next;

        this.options = $.extend({}, Pagination.DEFAULTS, data, options);
    };

    Pagination.VERSION = '1.0.1';

    Pagination.DEFAULTS = {
        "prev": "< Prev",
        "next": "Next >",
        "pageIndex": 0
    };

    Pagination.prototype.setOptions = function (options) {
        this.options = $.extend({}, this.options, options);

        var $el = this.$element;
        var prev = this.options.prev;
        var next = this.options.next;
        var pageIndex = this.options.pageIndex;
        var pageCount = this.options.pageCount;
        var change = this.options.change;

        var ul_html = '';
        if (pageCount == null) {
            ul_html = '';
        }
        else if (pageCount < 11) {
            for (var i = 0; i < pageCount; i++) {
                if (i == pageIndex) {
                    ul_html += '<li class="active"><a href="javascript:">' + (i + 1) + '</a></li>';
                }
                else {

                    ul_html += '<li><a href="javascript:">' + (i + 1) + '</a></li>';
                }
            }
        }
        else if (pageIndex < 5) {
            for (var i = 0; i < 6; i++) {
                if (i == pageIndex) {
                    ul_html += '<li class="active"><a href="javascript:">' + (i + 1) + '</a></li>';
                }
                else {

                    ul_html += '<li><a href="javascript:">' + (i + 1) + '</a></li>';
                }
            }
            ul_html += '<li><span>...</span></li>';
            ul_html += '<li><a href="javascript:">' + pageCount + '</a></li>';
            ul_html += '<li><a href="javascript:">' + next + '</a></li>';
        }
        else if (pageCount - pageIndex < 6) {
            ul_html += '<li><a href="javascript:">' + prev + '</a></li>';
            ul_html += '<li><a href="javascript:">1</a></li>';
            ul_html += '<li><span>...</span></li>';
            for (var i = pageCount - 6; i < pageCount ; i++) {
                if (i == pageIndex) {
                    ul_html += '<li class="active"><a href="javascript:">' + (i + 1) + '</a></li>';
                }
                else {

                    ul_html += '<li><a href="javascript:">' + (i + 1) + '</a></li>';
                }
            }
        }
        else {
            ul_html += '<li><a href="javascript:">' + prev + '</a></li>';
            ul_html += '<li><a href="javascript:">1</a></li>';
            ul_html += '<li><span>...</span></li>';

            ul_html += '<li><a href="javascript:">' + (pageIndex - 1) + '</a></li>';
            ul_html += '<li><a href="javascript:">' + pageIndex + '</a></li>';
            ul_html += '<li class="active"><a href="javascript:">' + (pageIndex + 1) + '</a></li>';
            ul_html += '<li><a href="javascript:">' + (pageIndex + 2) + '</a></li>';
            ul_html += '<li><a href="javascript:">' + (pageIndex + 3) + '</a></li>';

            ul_html += '<li><span>...</span></li>';
            ul_html += '<li><a href="javascript:">' + pageCount + '</a></li>';
            ul_html += '<li><a href="javascript:">' + next + '</a></li>';
        }

        $el.html(ul_html);

        //
        $el.find('>li:not(.active) a').click(function (event) {
            var index = $(this).text();
            if (index.indexOf(prev) > -1) {
                index = pageIndex;
            }
            else if (index.indexOf(next) > -1) {
                index = pageIndex + 2;
            }
            if (change != null) {
                change(index - 1);
            }
            event.preventDefault();
        });
    };

    // Plugin 
    var old = $.fn.pagination;

    $.fn.pagination = function (options) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.pagination');
            var opts = typeof options == 'object' && options;
            if (!data) $this.data('xd.pagination', (data = new Pagination(this, opts)));
            data.setOptions(opts);
        })
    };

    $.fn.pagination.Constructor = Pagination;

    // No conflict
    $.fn.pagination.noConflict = function () {
        $.fn.pagination = old;
        return this;
    };

}(jQuery);

// paginationGo options: {pageIndex,pageCount,change(pageIndex)}
+function ($) {
    "use strict";

    // Class
    var PaginationGo = function (element, options) {
        this.$element = $(element);
        var valueElement = this.$element.attr('data-value-element');
        this.$valueElement = $(valueElement);
        if (this.$valueElement.length == 0) {
            this.$valueElement = $('#' + valueElement);
        }
        this.options = $.extend({}, PaginationGo.DEFAULTS, options);

        //
        var instance = this;
        var $el = this.$element;
        $el.click(function (event) {
            var $ve = instance.$valueElement;
            if ($ve.length == 0) {
                $ve = $('#' + instance.$valueElement);
            }
            var pageCount = instance.options.pageCount;
            var index = $ve.val();
            var isValid = !isNaN(index) && index > 0;
            if (pageCount != null) {
                isValid = isValid && index <= pageCount;
            }
            if (isValid) {
                var change = instance.options.change;
                if (change != null) {
                    change(index - 1);
                }
            }
            else {
                $ve.focus().select();
            }
            event.preventDefault();
        });
    };

    PaginationGo.VERSION = '1.0.1';

    PaginationGo.DEFAULTS = {
        "pageIndex": 0
    };

    PaginationGo.prototype.setOptions = function (options) {
        this.options = $.extend({}, this.options, options);
        var pageIndex = this.options.pageIndex;
        var pageCount = this.options.pageCount;

        var $el = this.$element;
        var $ve = this.$valueElement;
        if ($ve.attr('type') == 'number') {
            $ve.attr('min', 1);
            if (pageCount != null) {
                $ve.attr('max', pageCount);
            }
        }

        if (pageCount == null) {
            $ve.val('');
        }
        else {
            var page_index = pageIndex + 2;
            if (page_index > pageCount) page_index = pageCount;
            $ve.val(page_index);
        }
    };

    // Plugin 
    var old = $.fn.paginationGo;

    $.fn.paginationGo = function (options) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.paginationGo');
            var opts = typeof options == 'object' && options;
            if (!data) $this.data('xd.paginationGo', (data = new PaginationGo(this, opts)));
            data.setOptions(opts);
        })
    };

    $.fn.paginationGo.Constructor = PaginationGo;

    // No conflict
    $.fn.paginationGo.noConflict = function () {
        $.fn.paginationGo = old;
        return this;
    };

}(jQuery);

// paginationInfo options: {pageIndex,itemCount,pageSize}
+function ($) {
    "use strict";

    // Class
    var PaginationInfo = function (element, options) {
        this.$element = $(element);
        this.options = $.extend({}, PaginationInfo.DEFAULTS, options);
    };

    PaginationInfo.VERSION = '1.0.1';

    PaginationInfo.DEFAULTS = {
        "pageIndex": 0
    };

    PaginationInfo.prototype.setOptions = function (options) {
        this.options = $.extend({}, this.options, options);

        var $el = this.$element;

        var html = $el.attr('data-html');
        if (html == null) {
            html = $el.html();
            $el.attr('data-html', html);
            $el.html('');
        }

        var pageIndex = this.options.pageIndex;
        var itemCount = this.options.itemCount;
        var pageSize = this.options.pageSize;
        var pageCount = Math.ceil(itemCount / pageSize);

        if (itemCount == null) return;

        var var_statements = 'var pageIndex=' + pageIndex + ';';
        var_statements += ' var itemCount=' + itemCount + ';';
        var_statements += ' var pageSize=' + pageSize + ';';
        var_statements += ' var pageCount=' + pageCount + ';';

        // {{...}}
        html = html.replace(/\{{2}.*?\}{2}/g, function (word) {
            var exp = word.slice(2, -2);
            exp = var_statements + ' ' + exp;
            return eval(exp);
        });
        $el.html(html);
    };

    // Plugin 
    var old = $.fn.paginationInfo;

    $.fn.paginationInfo = function (options) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.paginationInfo');
            var opts = typeof options == 'object' && options;
            if (!data) $this.data('xd.paginationInfo', (data = new PaginationInfo(this, opts)));
            data.setOptions(opts);
        })
    };

    $.fn.paginationInfo.Constructor = PaginationInfo;

    // No conflict
    $.fn.paginationInfo.noConflict = function () {
        $.fn.paginationInfo = old;
        return this;
    };

}(jQuery);

// tableHeadSorter options: {value,change(value)} // value: {"header":2,"updown":1}
+function ($) {
    "use strict";

    // Class
    var TableHeadSorter = function (element, options) {
        this.$element = $(element);
        var headerElement = this.$element.attr('data-header-element');
        this.$headerElement = $(headerElement);
        if (this.$headerElement.length == 0) {
            this.$headerElement = $('#' + headerElement);
        }
        var updownElement = this.$element.attr('data-updown-element');
        this.$updownElement = $(updownElement);
        if (this.$updownElement.length == 0) {
            this.$updownElement = $('#' + updownElement);
        }
        this.options = $.extend({}, TableHeadSorter.DEFAULTS, options);

        //
        var instance = this;
        var $th = this.$element.find('th.sort-both, th.sort-asc, th.sort-desc');
        $th.click(function (event) {
            var $he = instance.$headerElement;
            var $ud = instance.$updownElement;
            var change = instance.options.change;

            if ($(this).hasClass('sort-asc')) {
                $(this).removeClass('sort-asc');
                $(this).addClass('sort-desc');
                var header = $(this).attr('data-header');
                $he.val(header);
                $ud.val(1);
            }
            else if ($(this).hasClass('sort-desc')) {
                $(this).removeClass('sort-desc');
                $(this).addClass('sort-asc');
                var header = $(this).attr('data-header');
                $he.val(header);
                $ud.val(0);
            }
            else if ($(this).hasClass('sort-both')) {
                $th.removeClass('sort-asc').removeClass('sort-desc').addClass('sort-both');
                $(this).removeClass('sort-both');
                $(this).addClass('sort-asc');
                var header = $(this).attr('data-header');
                $he.val(header);
                $ud.val(0);
            }
            else {
                change = null;
            }

            if (change != null) {
                var value = {};
                value[$he.attr('name')] = $he.val();
                value[$ud.attr('name')] = $ud.val();
                change(value);
            }

            event.preventDefault();
        });
    };

    TableHeadSorter.VERSION = '1.0.1';

    TableHeadSorter.DEFAULTS = {
    };

    TableHeadSorter.prototype.setOptions = function (options) {
        this.options = $.extend({}, this.options, options);
        var $he = this.$headerElement;
        var $ud = this.$updownElement;
        var value = options.value;
        if (value != null) {
            $he.val(value[$he.attr('name')]);
            var ud = value[$ud.attr('name')];
            if (ud = 'asc') ud = 0;
            if (ud = 'desc') ud = 1;
            $ud.val(ud);
        }

        var $th = this.$element.find('th.sort-both, th.sort-asc, th.sort-desc');
        $th.removeClass('sort-asc').removeClass('sort-desc').addClass('sort-both');
        var header = $he.val();
        var updown = ($ud.val() == 0) ? 'asc' : 'desc';
        $th.filter('[data-header=' + header + ']').removeClass('sort-both').addClass('sort-' + updown);
    };

    // Plugin 
    function Plugin(options) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('xd.tableHeadSorter');
            var opts = typeof options == 'object' && options;
            if (!data) $this.data('xd.tableHeadSorter', (data = new TableHeadSorter(this, opts)));
            data.setOptions(opts);
        })
    }

    var old = $.fn.tableHeadSorter;

    $.fn.tableHeadSorter = Plugin;
    $.fn.tableHeadSorter.Constructor = TableHeadSorter;

    // No conflict
    $.fn.tableHeadSorter.noConflict = function () {
        $.fn.tableHeadSorter = old;
        return this;
    };

}(jQuery);

//------functions-----------------------------------------------------------------------------------

// $.toEncodedUrl(obj, path)
(function ($) {
    "use strict";

    var ToEncodedUrl = function (obj, path) {
        var search = '';
        $.each(obj, function (index, element) {
            search += index + '=' + element + '&';
        });
        if (search != '') {
            search = search.slice(0, search.length - 1);
            search = '?' + search;
        }

        if (path == null) {
            path = window.location.pathname;
        }
        return encodeURI(path + search);
    };

    ToEncodedUrl.VERSION = '1.0.1';

    $.toEncodedUrl = ToEncodedUrl;

})(jQuery);

// $.parseObject(encodedUrl)
(function ($) {
    "use strict";

    var ParseObject = function (encodedUrl) {
        var url = (encodedUrl == null) ? window.location.href : encodedUrl;
        url = decodeURI(url);

        var obj = {};
        var index = url.indexOf('?');
        if (index == -1) return obj;
        var search = url.slice(index + 1);
        var array = search.split('&');
        for (var i = 0; i < array.length; i++) {
            var pair = array[i].split('=');
            var key = pair[0];
            var value = pair[1];
            obj[key] = value;
        }
        return obj;
    };

    ParseObject.VERSION = '1.0.1';

    $.parseObject = ParseObject;

})(jQuery);

// $.isDateJson(string)
(function ($) {
    "use strict";

    var IsDateJson = function (string) {
        // '/Date(1355458892000+1200)/'
        var matches = /\/Date\(\d+(\+\d+)?\)\//.exec(string);
        if (matches != null) {
            if (matches[0] == string) {
                return true;
            }
        }
        return false;
    };

    IsDateJson.VERSION = '1.0.1';

    $.isDateJson = IsDateJson;

})(jQuery);

// $.parseDate(string, format) format: yyyy/yy mm/m dd/d hh/h ii/i ss/s ms
(function ($) {
    "use strict";

    var getUTCTime = function (s_data, s_time) {
        var data_array = s_data.split('-');
        var time_array = s_time.split(':');
        var sec_array = time_array[2].split('.');
        var sec = +sec_array[0];
        var ms = 0;
        if (sec_array[1] != null) {
            ms = sec_array[1].slice(0, 3);
        }
        var utcTime = Date.UTC(+data_array[0], data_array[1] - 1, +data_array[2], +time_array[0], +time_array[1], sec, ms);
        return utcTime;
    };

    var extract = function (string, format, selector) {
        var value = 0;
        var selector2 = selector + selector;
        var index = format.indexOf(selector2);
        if (index == -1) {
            index = format.indexOf(selector);
            if (index != -1) {
                value = string.substr(index, 1);
            }
        }
        else {
            value = string.substr(index, 2);
        }
        return value;
    };

    var ParseDate = function (string, dateFormat) {
        var format = dateFormat;
        if (dateFormat == '' || dateFormat == 'UTC' || dateFormat == 'local' || dateFormat == 'json') format = null;

        if (format != null) {
            var index = format.indexOf('ms');
            var ms = string.substr(index, 5);
            ms = parseInt(ms);

            var year = 0;
            index = format.indexOf('yyyy');
            if (index == -1) {
                index = format.indexOf('yy');
                if (index != -1) {
                    year = string.substr(index, 2);
                    year = '20' + year;
                }
            }
            else {
                year = string.substr(index, 4);
            }

            var month = extract(string, format, 'm');
            var day = extract(string, format, 'd');
            if (year * month * day == 0) return NaN;

            var hour = extract(string, format, 'h');
            var minute = extract(string, format, 'i');
            var second = extract(string, format, 's');

            var date = new Date(year, month - 1, day, hour, minute, second, ms);
            return date;
        }

        // '/Date(1355458892000+1200)/'
        var matches = /\/Date\(\d+(\+\d+)?\)\//.exec(string);
        if (matches != null) {
            if (matches[0] == string) {
                matches = /\d+/.exec(string);
                var date = new Date(+matches[0]);
                return date;
            }
        }

        // '2012-12-14T00:21:32.53403Z'
        matches = /\d{4}-\d{1,2}-\d{1,2}T\d{1,2}:\d{1,2}:\d{1,2}(\.\d{1,5})?Z/.exec(string);
        if (matches != null) {
            if (matches[0] == string) {
                var str = string.substring(0, string.length - 1);
                var array = str.split('T');
                var s_data = array[0];
                var s_time = array[1];
                var utcTime = getUTCTime(s_data, s_time);
                var date = new Date(utcTime);
                return date;
            }
        }

        // '2012-12-14T12:21:32.53403+12:00'
        matches = /\d{4}-\d{1,2}-\d{1,2}T\d{1,2}:\d{1,2}:\d{1,2}(\.\d{1,5})?[\+|-]\d{1,2}:\d{1,2}/.exec(string);
        if (matches != null) {
            if (matches[0] == string) {
                var array = string.split('T');
                var s_data = array[0];
                var time_zone_array = array[1].split(/[\+|-]/);
                var s_time = time_zone_array[0];
                var s_zone = time_zone_array[1];
                var s_zone_arry = s_zone.split(':');
                var zone_hour = s_zone_arry[0];
                var zone_min = s_zone_arry[1];
                var zone_time = (zone_hour * 3600 + zone_min * 60) * 1000;
                var sign = string.slice(-s_zone.length - 1)[0];
                var utcTime = getUTCTime(s_data, s_time);
                if (sign == '+') {
                    utcTime -= zone_time;
                }
                else {
                    utcTime += zone_time;
                }
                var date = new Date(utcTime);
                return date;
            }
        }

        // '2012-12-14T12:21' or '2012-12-14 12:21'
        matches = /\d{4}-\d{1,2}-\d{1,2}[T|\s]\d{1,2}:\d{1,2}/.exec(string);
        if (matches != null) {
            if (matches[0] == string) {
                var array = string.split(/[T|\s]/);
                var s_data = array[0];
                var s_time = array[1];
                var data_array = s_data.split('-');
                var time_array = s_time.split(':');
                var date = new Date(+data_array[0], data_array[1] - 1, +data_array[2], +time_array[0], +time_array[1]);
                return date;
            }
        }

        // '2012-12-14T12:21:32.53403' or '2012-12-14 12:21:32.53403'
        matches = /\d{4}-\d{1,2}-\d{1,2}[T|\s]\d{1,2}:\d{1,2}:\d{1,2}(\.\d{1,5})?/.exec(string);
        if (matches != null) {
            if (matches[0] == string) {
                var array = string.split(/[T|\s]/);
                var s_data = array[0];
                var s_time = array[1];
                var data_array = s_data.split('-');
                var time_array = s_time.split(':');
                var sec_array = time_array[2].split('.');
                var sec = +sec_array[0];
                var ms = 0;
                if (sec_array[1] != null) {
                    ms = sec_array[1].slice(0, 3);
                }
                var date = new Date(+data_array[0], data_array[1] - 1, +data_array[2], +time_array[0], +time_array[1], sec, ms);
                return date;
            }
        }

        // 2012-12-14
        matches = /\d{4}-\d{1,2}-\d{1,2}/.exec(string);
        if (matches != null) {
            if (matches[0] == string) {
                var array = string.split('-');
                var date = new Date(+array[0], array[1] - 1, +array[2]);
                return date;
            }
        }

        // '12:21'
        matches = /\d{1,2}:\d{1,2}/.exec(string);
        if (matches != null) {
            if (matches[0] == string) {
                var time_array = string.split(':');
                var stamp = (time_array[0] * 3600 + time_array[1] * 60) * 1000;
                var date = new Date(stamp);
                return date;
            }
        }

        // '12:21:32.53403'
        matches = /\d{1,2}:\d{1,2}:\d{1,2}(\.\d{1,5})?/.exec(string);
        if (matches != null) {
            if (matches[0] == string) {
                var time_array = string.split(':');
                var sec_array = time_array[2].split('.');
                var sec = +sec_array[0];
                var ms = 0;
                if (sec_array[1] != null) {
                    ms = sec_array[1].slice(0, 3);
                }
                var stamp = (time_array[0] * 3600 + time_array[1] * 60 + sec) * 1000 + ms;
                var date = new Date(stamp);
                return date;
            }
        }

        return NaN;
    };

    ParseDate.VERSION = '1.0.1';

    $.parseDate = ParseDate;

})(jQuery);

// $.toDateString(date, format) // format: UTC/local/json/yyyy/yy mm/m dd/d hh/h ii/i ss/s ms
(function ($) {
    "use strict";

    var getTimezoneString = function (date) {
        var offset = date.getTimezoneOffset();
        var abs_offset = Math.abs(offset);
        var hours = Math.floor(abs_offset / 60);
        var mins = abs_offset % 60;
        var suffix = (hours < 10) ? '0' + hours : hours.toString();
        suffix += ':';
        suffix += (mins < 10) ? '0' + mins : mins.toString();
        suffix = (offset < 0) ? '+' + suffix : '-' + suffix;
        return suffix;
    }

    var ToDateString = function (date, format) {
        if (isNaN(date)) return date.toString();

        if (format == null) {
            var s_date = ToDateString(date, 'date');
            var s_time = ToDateString(date, 'time');
            if (s_time == '00:00:00') {
                return s_date;
            } else {
                return s_date + ' ' + s_time;
            }
        }

        // '/Date(1355458892000+1200)/'
        if (format == 'json') {
            var number = date.getTime();
            var suffix = getTimezoneString(date).replace(':', '');
            return '/Date(' + number + suffix + ')/';
        }

        // '2012-12-14T00:21:32.534Z'
        if (format == 'UTC') {
            var year = date.getUTCFullYear();
            var month = date.getUTCMonth() + 1;
            var day = date.getUTCDate();
            var s_month = (month < 10) ? '0' + month.toString() : month.toString();
            var s_day = (day < 10) ? '0' + day.toString() : day.toString();
            var s_date = year + '-' + s_month + '-' + s_day;

            var hours = date.getUTCHours();
            var minutes = date.getUTCMinutes();
            var seconds = date.getUTCSeconds();
            var s_hours = (hours < 10) ? '0' + hours.toString() : hours.toString();
            var s_minutes = (minutes < 10) ? '0' + minutes.toString() : minutes.toString();
            var s_seconds = (seconds < 10) ? '0' + seconds.toString() : seconds.toString();
            var s_time = s_hours + ":" + s_minutes + ":" + s_seconds;
            var ms = date.getMilliseconds();
            if (ms > 0) {
                s_time += '.' + ms;
            }
            return s_date + 'T' + s_time + 'Z';
        }

        // '2012-12-14T12:21:32.534+12:00'
        if (format == 'local') {
            var s_date = ToDateString(date, 'date');
            var s_time = ToDateString(date, 'time');
            var ms = date.getMilliseconds();
            if (ms > 0) {
                s_time += '.' + ms;
            }
            var s_zone = getTimezoneString(date);
            return s_date + 'T' + s_time + s_zone;
        }

        // '2012-12-14 12:21:32'
        if (format == 'datetime') {
            var s_date = ToDateString(date, 'date');
            var s_time = ToDateString(date, 'time');
            return s_date + ' ' + s_time;
        }

        // '2012-12-14'
        if (format == 'date') {
            var year = date.getFullYear();
            var month = date.getMonth() + 1;
            var day = date.getDate();
            var s_month = (month < 10) ? '0' + month.toString() : month.toString();
            var s_day = (day < 10) ? '0' + day.toString() : day.toString();
            return year + '-' + s_month + '-' + s_day;
        }

        // '12:21:32'
        if (format == 'time') {
            var hours = date.getHours();
            var minutes = date.getMinutes();
            var seconds = date.getSeconds();
            var s_hours = (hours < 10) ? '0' + hours.toString() : hours.toString();
            var s_minutes = (minutes < 10) ? '0' + minutes.toString() : minutes.toString();
            var s_seconds = (seconds < 10) ? '0' + seconds.toString() : seconds.toString();
            return s_hours + ":" + s_minutes + ":" + s_seconds;
        }

        // yyyy/yy mm/m dd/d hh/h ii/i ss/s ms
        var year = date.getFullYear();
        var month = date.getMonth() + 1;
        var hours = date.getHours();
        var minutes = date.getMinutes();
        var day = date.getDate();
        var seconds = date.getSeconds();
        var mseconds = date.getMilliseconds();

        var string = format;
        string = string.replace(/ms/i, mseconds);
        string = string.replace(/yyyy/i, year);
        string = string.replace(/yy/i, year.toString().slice(2));
        string = (month < 10) ? string.replace(/mm/i, '0' + month) : string.replace(/mm/i, month);
        string = string.replace(/m/i, month);
        string = (day < 10) ? string.replace(/dd/i, '0' + day) : string.replace(/dd/i, day);
        string = string.replace(/d/i, day);
        string = (hours < 10) ? string.replace(/hh/i, '0' + hours) : string.replace(/hh/i, hours);
        string = string.replace(/h/i, hours);
        string = (minutes < 10) ? string.replace(/ii/i, '0' + minutes) : string.replace(/ii/i, minutes);
        string = string.replace(/i/i, minutes);
        string = (seconds < 10) ? string.replace(/ss/i, '0' + seconds) : string.replace(/ss/i, seconds);
        string = string.replace(/s/i, seconds);
        return string;
    };

    ToDateString.VERSION = '1.0.1';

    $.toDateString = ToDateString;

})(jQuery);
